package com.qianxun.module.datasource1.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qianxun.framework.common.util.AssertUtil;
import com.qianxun.framework.common.util.NumberCodeGenerator;
import com.qianxun.framework.common.util.ObjectUtil;
import com.qianxun.framework.common.util.StringUtil;
import com.qianxun.module.base.util.MenuTreeVoUtil;
import com.qianxun.module.datasource1.admin.constact.SysMenuConstant;
import com.qianxun.module.datasource1.admin.dto.SysMenuDTO;
import com.qianxun.module.datasource1.admin.entity.SysMenu;
import com.qianxun.module.datasource1.admin.mapper.SysMenuMapper;
import com.qianxun.module.datasource1.admin.service.SysMenuRoleRelationService;
import com.qianxun.module.datasource1.admin.service.SysMenuService;
import com.qianxun.module.base.vo.MenuTreeVo;
import com.qianxun.module.base.bo.ZTreeNode;
import com.qianxun.module.base.exception.ServiceInterruptionException;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

/**
 * <p>
 * 菜单 记录系统所有的功能列表，并提供功能是否权限才能访问 服务实现类
 * </p>
 *
 * @author admin
 * @since 2019-11-14
 */
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements SysMenuService {

    @Resource
    private SysMenuRoleRelationService sysRoleMenuRelationService;

    @Override
    public void add(SysMenuDTO query) {
        SysMenu sysMenu = new SysMenu();
        ObjectUtil.switchAllFieldValue(sysMenu, query);
        //初始化默认值
        sysMenu.init();

        SysMenu parent = selectOneByIdDescLimit1(query.getPid());

        if(parent == null && query.getPid() != 0){
            throw ServiceInterruptionException.fail(400 ,"上级菜单不存在, pid：" + query.getPid());
        }

        String code = null;
        NumberCodeGenerator numberCodeGenerator = NumberCodeGenerator.build();
        if(sysMenu.getPid() == 0){
            SysMenu lastBrother = selectOneByPidDescLimit1(0);
            try {
                code = numberCodeGenerator.next(lastBrother.getCode());
            } catch (Exception e) {
                throw ServiceInterruptionException.fail(500 ,"功能角色编码不可分配，请联系管理员");
            }
        }else{
            SysMenu lastBrother = selectOneByPidDescLimit1(parent.getId());
            try {
                code = lastBrother == null ? numberCodeGenerator.child(parent.getCode()): numberCodeGenerator.next(lastBrother.getCode());
            } catch (Exception e) {
                throw ServiceInterruptionException.fail(500 ,"功能角色编码不可分配，请联系管理员");
            }
        }

        sysMenu.setCode(code);

        save(sysMenu);
    }

    @Override
    public void deleteSelfAndChildrenById(Long id) {
        SysMenu sysMenu = this.baseMapper.selectById(id);
        if(sysMenu == null){
            return;
        }
        //通过菜单编号删除本身和所有子节点
        String rootCode = NumberCodeGenerator.build().original(sysMenu.getCode());
        //右模糊根编码，即可得到当前编码下所有孩子节点
        Wrapper wrapper = new QueryWrapper<SysMenu>().lambda().likeRight(SysMenu::getCode ,rootCode);
        remove(wrapper);

        //删除菜单和角色的关联数据
        sysRoleMenuRelationService.removeByMenuId(sysMenu.getId());
    }

    @Override
    public List<MenuTreeVo> searchVerticalMenuTree(long userId) {
        List<SysMenu> list = this.baseMapper.selectListBy(userId ,null ,1 ,SysMenuConstant.SHOW_MODE_VERTICAL ,SysMenuConstant.TYPE_MENU);

        return MenuTreeVoUtil.switchMenuTree(list ,0L);
    }

    @Override
    public List<MenuTreeVo> searchLevelMenuTree(Long userId, long menuId) {
        SysMenu parentMenu = getById(menuId);
        AssertUtil.notNull(parentMenu ,ServiceInterruptionException.fail(400 , StringUtil.concat("不存在指定菜单",menuId)));
        String originalCode = NumberCodeGenerator.build().original(parentMenu.getCode());

        List<SysMenu> list = this.baseMapper.selectListBy(userId ,originalCode.concat("%") ,1 , SysMenuConstant.SHOW_MODE_LEVEL ,SysMenuConstant.TYPE_MENU);
        return MenuTreeVoUtil.switchMenuTree(list ,menuId);
    }

    @Override
    public List<ZTreeNode> searchMenuTreeByRoleId(Long roleId) {
        List<Long> menuIdList = sysRoleMenuRelationService.listMenuIdByRoleId(roleId);
        List<SysMenu> list = list();
        List<ZTreeNode> zTreeNodeList = new ArrayList<>(list.size());
        list.forEach(sysMenu -> {
            ZTreeNode zTreeNode = new ZTreeNode();
            zTreeNode.setName(sysMenu.getName()).setId(sysMenu.getId()).setPId(sysMenu.getPid());
            if(menuIdList.contains(sysMenu.getId())){
                zTreeNode.setChecked(true);
            }
            zTreeNodeList.add(zTreeNode);
        });

        zTreeNodeList.add(ZTreeNode.createParent());
        return zTreeNodeList;
    }

    @Override
    public List<SysMenu> getAllAndOrder() {
        return baseMapper.selectAllAndOrderByPidSort();
    }

    @Override
    public SysMenu getOneMaxSortMenuByPid(long pid) {
        return baseMapper.selectOneMaxSortMenuByPid(pid);
    }

    private List<SysMenu> listEnableMenu(){
        Wrapper wrapper = new QueryWrapper<SysMenu>().lambda().eq(SysMenu::getStatus ,1).eq(SysMenu::getMenuFlag ,1);
        return this.baseMapper.selectList(wrapper);
    }

    private SysMenu selectOneByIdDescLimit1(long id){
        Wrapper wrapper = new QueryWrapper<SysMenu>().lambda().eq(SysMenu::getId ,id)
                .last("ORDER BY id DESC LIMIT 1");
        return this.baseMapper.selectOne(wrapper);
    }

    private SysMenu selectOneByPidDescLimit1(long pid){
        Wrapper wrapper = new QueryWrapper<SysMenu>().lambda().eq(SysMenu::getPid ,pid)
                .last("ORDER BY id DESC LIMIT 1");
        return this.baseMapper.selectOne(wrapper);
    }
}
